﻿
// legendDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "legend.h"
#include "legendDlg.h"
#include "afxdialogex.h"
#include <functional>
#include "dmDll.h"

HHOOK keyboardHook = 0;
ClegendDlg* g_dlg = 0;

// 可变参数模板函数
std::string format_string(const char* format, ...) {
	char buf[256]; // 缓冲区大小可以根据实际需求调整
	va_list args; // 可变参数列表
	va_start(args, format); // 初始化可变参数列表

	// 使用 vsnprintf 将格式化后的字符串写入缓冲区
	vsnprintf(buf, sizeof(buf), format, args);

	va_end(args); // 结束可变参数列表

	// 返回格式化后的字符串
	return std::string(buf);
}

//选中怪物 543A98
class CMonster
{
public:
	CMonster() {};
	~CMonster() {};
public:
	std::string m_name;
	UINT32 m_obj;
	int m_hp;
	int m_hpMax;
	UINT32 m_x;
	UINT32 m_y;
	bool m_是否死亡 = false;
	char m_类型; // 0x32:npc 0x0:玩家

public:
	static void find(std::function<void(CMonster*)>fun)
	{
		//目标怪物 5ADC60
		dmsoft* dm = g_dlg->m_dm;
		UINT32 begin = dm->ReadInt(g_dlg->m_hwnd, "[[<星月传奇[全新二季]②.exe>+4C2FD4]+c0]+4", 0);
		UINT32 length = dm->ReadInt(g_dlg->m_hwnd, "[[<星月传奇[全新二季]②.exe>+4C2FD4]+c0]+8", 0);
		for (UINT32 i = 0; i < length; i++)
		{
			UINT32 obj = dm->ReadIntAddr(g_dlg->m_hwnd, begin + i * 4, 0);
			CMonster* m = new CMonster();
			m->m_obj = obj;
			m->m_name = dm->ReadStringAddr(g_dlg->m_hwnd, dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x13d0, 0), 0, 0);
			m->m_x = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x454, 0);
			m->m_y = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x454 + 0x4, 0);
			m->m_hp = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x228, 0);
			m->m_hpMax = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x228 + 0x8, 0);
			m->m_类型 = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x2d, 2);
			m->m_是否死亡 = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x1e9, 2);
			//PrintA("fs: %s %x\n" , m->m_name.c_str() , m->m_是否死亡);
			fun(m);
			delete m;
		}
	}

	static void 挂机开关(bool 开关)
	{
		dmsoft* dm = g_dlg->m_dm;
		long hwnd = g_dlg->m_hwnd;
		long ret = dm->ReadInt(hwnd, "<星月传奇[全新二季]②.exe>+543AA0", 0);
		if (开关)
		{
			if (ret == 0)
			{
				PrintA("fs:开启挂机!\n");
				dm->WriteInt(hwnd, "<星月传奇[全新二季]②.exe>+543AA0", 0, -1);
			}
		}
		else
		{
			if (ret == -1)
			{
				PrintA("fs:关闭挂机!\n");
				dm->WriteInt(hwnd, "<星月传奇[全新二季]②.exe>+543AA0", 0, 0);
			}
			
		}
	}

	static bool 宝宝是否在范围内(int 距离)
	{
		dmsoft* dm = g_dlg->m_dm;
		long hwnd = g_dlg->m_hwnd;
		CMonster 人物 = 取自身();
		bool ret = false;
		find([&](CMonster* m) {
			if(m->m_类型 != 0x32 && m->m_类型 != 0x0)
			if (m->m_name.find("变异骷髅") != -1 || m->m_name.find("神兽") != -1 || m->m_name.find("圣兽") != -1)
			{
				if (m->m_name.find(人物.m_name) != -1 && m->m_是否死亡 == false)
				{
					//PrintA("与宝宝距离:%d\n", 两点距离(人物.m_x, 人物.m_y, m->m_x, m->m_y));
					if (两点距离(人物.m_x, 人物.m_y, m->m_x, m->m_y) < 距离)
					{
						ret = true;
					}
				}
			}

			});

		return ret;
	}

	static float 取人物血量百分比()
	{
		dmsoft* dm = g_dlg->m_dm;
		long hwnd = g_dlg->m_hwnd;
		CMonster 人物 = 取自身();
		bool ret = false;
		return (float)(人物.m_hp) / (float)(人物.m_hpMax);
	}

	static bool 范围内是否有怪(int 距离)
	{
		dmsoft* dm = g_dlg->m_dm;
		long hwnd = g_dlg->m_hwnd;
		CMonster 人物 = 取自身();
		bool ret = false;
		int sum = 0;
		find([&](CMonster* m) {
			if (m->m_类型 != 0)
			{
				if (m->m_name.find("变异骷髅") == -1 && m->m_name.find("神兽") == -1 && m->m_name.find("圣兽") == -1 && m->m_是否死亡 == false && 人物.m_obj != m->m_obj)
				{
					if (两点距离(人物.m_x, 人物.m_y, m->m_x, m->m_y) <= 距离)
					{
						sum++;
					}

				}
			}

			
				
			});

		if (sum > 2)
		{
			ret = true;
		}

		return ret;
	}

	static int 两点距离(int x, int y, int x1, int y1)
	{
		int deltaX = x - x1;
		int deltaY = y - y1;
		double distance = std::sqrt(deltaX * deltaX + deltaY * deltaY);
		return static_cast<int>(distance);
	}

	static CMonster 取自身()
	{
		dmsoft* dm = g_dlg->m_dm;
		long hwnd = g_dlg->m_hwnd;
		UINT32 obj = dm->ReadInt(g_dlg->m_hwnd, "<星月传奇[全新二季]②.exe>+543B50", 0);
		CMonster m;
		m.m_obj = obj;
		m.m_name = dm->ReadStringAddr(g_dlg->m_hwnd, dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x13d0, 0), 0, 0);
		m.m_x = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x454, 0);
		m.m_y = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x454 + 0x4, 0);
		m.m_hp = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x228, 0);
		m.m_hpMax = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x228 + 0x8, 0);
		m.m_类型 = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x25, 2);
		m.m_是否死亡 = dm->ReadIntAddr(g_dlg->m_hwnd, obj + 0x1e9, 2);
		return m;
	}

	static void 回收()
	{
		dmsoft* dm = g_dlg->m_dm;
		long hwnd = g_dlg->m_hwnd;
		long long moudle =  dm->GetModuleBaseAddr(hwnd, "星月传奇[全新二季]②.exe");
		int socket = dm->ReadInt(hwnd, "[[[[<星月传奇[全新二季]②.exe>+3B5448]]+2f8]+90]+4", 0);

		static long long buf_垃圾回收 = 0;
		static long long buf_沃玛回收 = 0;
		static long long buf_祖玛回收 = 0;
		static long long buf_赤月回收 = 0;
		static long long buf_打开回收 = 0;
	
		if (!buf_打开回收)
		{
			buf_打开回收 = dm->VirtualAllocEx(hwnd, 0, 0x50, 2);
			dm->WriteDataAddr(hwnd, buf_打开回收, "23 36 3C 3C 3C 3C 3C 3C 3C 3C 3C 3C 3E 67 3C 3C 40 3C 3C 3C 3C 3C 3C 3C 21");
		}

		if (!buf_垃圾回收)
		{
			buf_垃圾回收 = dm->VirtualAllocEx(hwnd , 0 , 0x50 , 2);
			dm->WriteDataAddr(hwnd , buf_垃圾回收 , "23 38 44 4A 43 52 3E 3C 3C 3C 3C 3C 3F 6F 3C 6C 3C 3C 3C 3C 3C 3C 3C 3C 4C 48 3E 68 6A 7B 5C 21");
		}

		if (!buf_沃玛回收)
		{
			buf_沃玛回收 = dm->VirtualAllocEx(hwnd, 0, 0x50, 2);
			dm->WriteDataAddr(hwnd, buf_沃玛回收, "23 34 44 4A 43 52 3E 3C 3C 3C 3C 3C 3F 6F 3C 6C 3C 3C 3C 3C 3C 3C 3C 3C 4C 48 77 52 6C 6A 66 77 72 48 67 51 21");
		}

		if (!buf_祖玛回收)
		{
			buf_祖玛回收 = dm->VirtualAllocEx(hwnd, 0, 0x50, 2);
			dm->WriteDataAddr(hwnd, buf_祖玛回收, "23 38 44 4A 43 52 3E 3C 3C 3C 3C 3C 3F 6F 3C 6C 3C 3C 3C 3C 3C 3C 3C 3C 4C 49 5B 62 6C 6A 66 77 72 48 67 51 21");
		}

		dm->AsmAdd(format_string("mov eax,%x", buf_打开回收 + 1).c_str());
		dm->AsmAdd(format_string("mov ebx,%x", moudle + 0x3B01C8).c_str());
		dm->AsmAdd("mov bl , byte ptr[ebx]");
		dm->AsmAdd("add bl , 30");
		dm->AsmAdd("mov byte ptr[eax] , bl");
		dm->AsmAdd("push 0");
		dm->AsmAdd("push 19");
		dm->AsmAdd(format_string("mov ebx,%x", buf_打开回收).c_str());
		dm->AsmAdd("push ebx");
		dm->AsmAdd(format_string("mov eax,%x", socket).c_str());
		dm->AsmAdd("push eax");
		dm->AsmAdd(format_string("mov edx,%x", ::send).c_str());
		dm->AsmAdd("call edx");
		dm->AsmCall(hwnd, 6);
		Sleep(500);
		
		dm->AsmAdd(format_string("mov eax,%x", buf_垃圾回收 + 1).c_str());
		dm->AsmAdd(format_string("mov ebx,%x", moudle + 0x3B01C8).c_str());
		dm->AsmAdd("mov bl , byte ptr[ebx]");
		dm->AsmAdd("add bl , 30");
		dm->AsmAdd("mov byte ptr[eax] , bl");
		dm->AsmAdd("push 0");
		dm->AsmAdd("push 20");
		dm->AsmAdd(format_string("mov ebx,%x", buf_垃圾回收).c_str());
		dm->AsmAdd("push ebx");
		dm->AsmAdd(format_string("mov eax,%x", socket).c_str());
		dm->AsmAdd("push eax");
		dm->AsmAdd(format_string("mov edx,%x", ::send).c_str());
		dm->AsmAdd("call edx");
		dm->AsmCall(hwnd , 6);


		dm->AsmAdd(format_string("mov eax,%x", buf_沃玛回收 + 1).c_str());
		dm->AsmAdd(format_string("mov ebx,%x", moudle + 0x3B01C8).c_str());
		dm->AsmAdd("mov bl , byte ptr[ebx]");
		dm->AsmAdd("add bl , 30");
		dm->AsmAdd("mov byte ptr[eax] , bl");
		dm->AsmAdd("push 0");
		dm->AsmAdd("push 25");
		dm->AsmAdd(format_string("mov ebx,%x", buf_沃玛回收).c_str());
		dm->AsmAdd("push ebx");
		dm->AsmAdd(format_string("mov eax,%x", socket).c_str());
		dm->AsmAdd("push eax");
		dm->AsmAdd(format_string("mov edx,%x", ::send).c_str());
		dm->AsmAdd("call edx");
		dm->AsmCall(hwnd, 6);


		//dm->AsmAdd(format_string("mov eax,%x", buf_祖玛回收 + 1).c_str());
		//dm->AsmAdd(format_string("mov ebx,%x", moudle + 0x3B01C8).c_str());
		//dm->AsmAdd("mov bl , byte ptr[ebx]");
		//dm->AsmAdd("add bl , 30");
		//dm->AsmAdd("mov byte ptr[eax] , bl");
		//dm->AsmAdd("push 0");
		//dm->AsmAdd("push 25");
		//dm->AsmAdd(format_string("mov ebx,%x", buf_祖玛回收).c_str());
		//dm->AsmAdd("push ebx");
		//dm->AsmAdd(format_string("mov eax,%x", socket).c_str());
		//dm->AsmAdd("push eax");
		//dm->AsmAdd(format_string("mov edx,%x", ::send).c_str());
		//dm->AsmAdd("call edx");
		//dm->AsmCall(hwnd, 6);
		Sleep(500);
		dm->KeyPress(13);
	}
};

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
	ClegendDlg* dlg = (ClegendDlg*)lpParameter;

	long 回收时间 = GetTickCount();
	while (true)
	{
	
		if (dlg->m_hwnd && dlg->m_开启保护)
		{
			
			//加血

			if (CMonster::取人物血量百分比() < 0.9)
			{
				dlg->m_dm->KeyPress(112);
				Sleep(500);
			}
			//回收
			if (GetTickCount() - 回收时间 > 6 * 60  * 1000)
			{
				CMonster::回收();
				回收时间 = GetTickCount();
			}
			if (dlg->m_范围判断)
			{
				if (CMonster::范围内是否有怪(3))
				{
					
					CMonster::挂机开关(false);
				}
				else
				{
					CMonster::挂机开关(true);
				}
			}

			if (CMonster::宝宝是否在范围内(6) == false)
			{
				PrintA("宝宝不在范围内，开始召唤宝宝!\n");
				dlg->m_dm->KeyPress(119);
				Sleep(500);
			}
			
		}

		Sleep(10);
	}



	return 0;
}

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// ClegendDlg 对话框



ClegendDlg::ClegendDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_LEGEND_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void ClegendDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(ClegendDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, &ClegendDlg::OnBnClickedButton1)
	ON_WM_CLOSE()
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BUTTON2, &ClegendDlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &ClegendDlg::OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON4, &ClegendDlg::OnBnClickedButton4)
	ON_BN_CLICKED(IDC_BUTTON5, &ClegendDlg::OnBnClickedButton5)
	ON_BN_CLICKED(IDC_BUTTON6, &ClegendDlg::OnBnClickedButton6)
END_MESSAGE_MAP()


// ClegendDlg 消息处理程序

BOOL ClegendDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	//::CoInitializeEx(NULL, 0);
	g_dlg = this;

	bool ret = LoadDmMemory(dm, 7716288, MemoryLoad, 221184);
	m_dm = new dmsoft;
	SetWindowTextA(m_dm->Ver());

	// 注册
	long dm_ret = m_dm->RegEx("aa328496536790abb00a0527d4c4684134b8614392b", "", "121.204.252.143|121.204.253.161|125.77.165.62|125.77.165.131");
	switch (dm_ret) {
	case 1:
	{
		break;
	}
	case -1:
	{
		::MessageBoxA(0, "无法连接网络,(可能防火墙拦截,如果可以正常访问大漠插件网站，那就可以肯定是被防火墙拦截)\n", "", 0);
		return false;
	}
	case -2:
	{
		::MessageBoxA(0, "进程没有以管理员方式运行. (出现在win7 win8 vista 2008.建议关闭uac)", "", 0);
		return false;
	}
	case 0:
	{
		::MessageBoxA(0, "失败 (未知错误)\n", "", 0);
		return false;
	}
	case 2:
	{
		::MessageBoxA(0, "余额不足\n", "", 0);
		return false;
	}
	}

	HANDLE hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL);

	SetTimer(1, 100 , 0);

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void ClegendDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void ClegendDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR ClegendDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void ClegendDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	m_dm->WriteInt(m_hwnd, "<星月传奇[全新二季]②.exe>+543AA0", 0, -1);
}


void ClegendDlg::OnClose()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialogEx::OnClose();
}


void ClegendDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	switch (nIDEvent)
	{
	case 1:
	{
		if (GetAsyncKeyState(VK_F5) & 0x8000 && m_hwnd == 0)
		{
			m_hwnd =  m_dm->GetMousePointWindow();
			char str[100] = {0};
			SetWindowTextA(itoa(m_hwnd , str , 10));
		}
		break;
	}
	default:
		break;
	}
	CDialogEx::OnTimer(nIDEvent);
}


void ClegendDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	m_dm->WriteInt(m_hwnd, "<星月传奇[全新二季]②.exe>+543AA0", 0, 0);
}


//static void PrintA(const char* format, ...)
//{
//	va_list args;
//	va_start(args, format);
//	char buff[1024] = { 0 };
//	vsprintf(buff, format, args);
//	va_end(args);
//	OutputDebugStringA(buff);
//	printf(buff);
//}





void ClegendDlg::OnBnClickedButton3()
{
	// TODO: 在此添加控件通知处理程序代码
	m_开启保护 = true;

	if (m_hwnd)
	{
		if (m_dm->BindWindowEx(m_hwnd, "normal", "normal", "windows", "", 0))
		{
			
	
		}
		else
		{
			MessageBoxA("绑定失败\n");
		}
	}
}


void ClegendDlg::OnBnClickedButton4()
{
	// TODO: 在此添加控件通知处理程序代码
	m_开启保护 = false;
	if (m_hwnd)
	{
		m_dm->UnBindWindow();
	}
}


void ClegendDlg::OnBnClickedButton5()
{
	m_范围判断 = true;
	// TODO: 在此添加控件通知处理程序代码
}


void ClegendDlg::OnBnClickedButton6()
{
	// TODO: 在此添加控件通知处理程序代码
	m_范围判断 = false;
}
